/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.logging.appender;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import org.zhiqim.kernel.constants.CodeConstants;
import org.zhiqim.kernel.logging.LogAppender;
import org.zhiqim.kernel.logging.LogFactory;
import org.zhiqim.kernel.util.Files;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Stringx;

/**
 * 文件增加器，定义抽象类，完成文件写、创建关闭操作
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
public abstract class FileAppender implements LogAppender, CodeConstants
{
    protected String filePattern;             //文件日志打印格式
    protected String filePath;                //文件路径
    protected int fileMaxNum;                 //文件最多保存个数
    protected int fileMaxSize;                //文件允许大小,单位字节
    
    protected String fileEncoding = _UTF_8_;  //文件编码，默认UTF-8，如果unix/liunx配置的是zh_CN.GB18030则设置成GBK，有利于tail查看文件
    protected PrintWriter writer;             //输出器
    
    //保存两个文件属性，在使用时无需再从filePath截取
    protected String fileDir;
    protected String fileName;
    
    /***********************************************************************************/
    //提供子类调用的方法
    /***********************************************************************************/

    /** 打印日志信息 */
    protected void print(int level, String message, Throwable throwable)
    {
        if (message != null)
        {//消息
            message = LogFactory.format(filePattern, message, LogFactory.getLevel(level));
            writer.print(message);
            writer.flush();
        }
        
        if (throwable != null)
        {//异常
            throwable.printStackTrace(writer);
        }
    }
    
    /** 获取输出器 */
    protected PrintWriter getWriter()
    {
        return writer;
    }

    /** 判断输出器 */
    protected void closeWriter()
    {
        if (writer != null)
        {
            writer.close();
            writer = null;
        }
    }
    
    /** 创建输出器 */
    protected void createWriter() 
    {
        try 
        {
            String fileDir = Files.getFileDirPath(filePath);
            if (!Files.isDirectory(fileDir))
                Files.mkDirectory(fileDir);
            
            File file = new File(filePath);
            boolean exists = file.exists();
            
            OutputStream os = new FileOutputStream(filePath, true);
            if (!exists && _UTF_8_.equals(fileEncoding))
            {//加上UTF-8的BOM，保证Windows和Linux都能识别
                os.write(0xEF);os.write(0xBB);os.write(0xBF);
                os.flush();
            }
            
            OutputStreamWriter osw = new OutputStreamWriter(os, fileEncoding);
            writer = new PrintWriter(osw, true);
        } 
        catch(IOException e) 
        {
            if (e instanceof InterruptedIOException) 
            {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    /** 获取文件大小 */
    protected long getFileSize()
    {
        File file = new File(filePath);
        if (!Files.isFile(file))
            return 0;
        
        return file.length();
    }
    
    /***********************************************************************************/
    //参数配置 getter / setter
    /***********************************************************************************/

    public String getFilePattern()
    {
        return filePattern;
    }
    
    public void setFilePattern(String filePattern)
    {
        this.filePattern = Stringx.trim(filePattern);
    }

    public String getFileDir()
    {
        return fileDir;
    }
    
    public String getFileName()
    {
        return fileName;
    }
    
    public String getFilePath()
    {
        return filePath;
    }

    public void setFilePath(String filePath)
    {
        this.filePath = Stringx.trim(filePath);
        this.fileDir = Files.toLinuxPath(Files.getFileDirPath(this.filePath));
        this.fileName = Files.getFileName(this.filePath);
    }
    
    public void setFilePathOnly(String filePath)
    {
        this.filePath = filePath;
    }
    
    public int getFileMaxNum()
    {
        return fileMaxNum;
    }

    public void setFileMaxNum(int fileMaxNum)
    {
        this.fileMaxNum = fileMaxNum;
    }
    
    public int getFileMaxSize()
    {
        return fileMaxSize;
    }

    public void setFileMaxSize(int fileMaxSize)
    {
        this.fileMaxSize = fileMaxSize * 1024 * 1024;
    }
    
    public String getFileEncoding()
    {
        return fileEncoding;
    }

    public void setFileEncoding(String fileEncoding)
    {
        this.fileEncoding = Strings.trim(fileEncoding, _UTF_8_);
    }
}